#include"mprpcchannel.h"
#define test


void MprpcChannel::CallMethod(const ::google::protobuf::MethodDescriptor* method,
                             ::google::protobuf::RpcController* controller,
                             const ::google::protobuf::Message* request,
                             ::google::protobuf::Message* response,
                             ::google::protobuf::Closure* done)
{
   /*
   
   在这里method不用更改，你用哪个方法，protobuf已经根据服务proto文件对某个service某个rpc方法编了号，如调用Login，底层则会根据号检索到login
   在这里做的事如下：
    1.将request封装成约定格式，请求头字节数（该段大小4字节）+请求头（服务名，方法名，参数字节数）（rpcheader.prpto封装了）+参数（即request中的）
    2.使用muduo库创建客户端，发送1步骤序列后的信息于初始化读入（serverip,serverport）的rpc服务端
   */ 
    const google::protobuf::ServiceDescriptor * service = method->service();
    std::string service_name = service->name(); 
    std::string method_name = method->name();

    //获取参数的序列化字符串长度arg_size
    std::string args_str;
    uint32_t arg_size = 0;;
    if(request->SerializeToString(&args_str)){
        arg_size = args_str.size();
    }
    else{
        // std::cout<<"Serialize request error!"<<std::endl;
        controller->SetFailed("Serialize request error!");
        return;
    }

    //定义rpc的请求head
    mprpc::Rpcheader rpcHeader;
    rpcHeader.set_serivice_name(service_name);
    rpcHeader.set_method_name(method_name);
    rpcHeader.set_args_size(arg_size);

    std::string rpc_header_str;
    uint32_t header_size = 0;
    if(rpcHeader.SerializeToString(&rpc_header_str)){
        header_size = rpc_header_str.size(); 
    }
    else{
        // std::cout<<"serialize rpc header error!"<<std::endl;
        controller->SetFailed("serialize rpc header error!");
        return;
    }


    //封装为已规定的格式
    std::string send_rpc_str;
    send_rpc_str.insert(0,std::string((char*)&header_size,4)); //head_size
    send_rpc_str+=rpc_header_str; //rpcheader
    send_rpc_str+=args_str; //arg_str

#ifdef test
    std::cout<<"=============================================="<<std::endl;
    std::cout<<"header_size: "<<header_size<<std::endl;
    std::cout<<"rpc_header_str: "<<rpc_header_str<<std::endl;
    std::cout<<"service name: "<<service_name<<std::endl;
    std::cout<<"method_name: "<<method_name<<std::endl;
    std::cout<<"args_str: "<<args_str<<std::endl;
    std::cout<<"=============================================="<<std::endl;

#endif

    //使用TCP编程，完成rpc方法的远程调用
    int clientfd =  socket(AF_INET,SOCK_STREAM,0);
    if(clientfd==-1){
        // std::cout<<"create socket error! errno: "<<errno<<std::endl;
        //为携带一个errno，组装一个字符串
        char errtxt[512] = {0};
        sprintf(errtxt,"create socket error! errno: %d",errno);
        controller->SetFailed(errtxt);
        // perror("socket");
        close(clientfd);
        exit(EXIT_FAILURE);
    }

    //读取配置信息相关内容
    MprpcConfig service_config = MprpcApplication::GetInstance().GetConfig();
    // std::string rpcservice_ip = service_config.Load("rpcserverip");
    // std::string rpcservice_port = service_config.Load("rpcserverport");

    //下面两端，zkclient已经帮忙封装好了，自动读取配置文件封装了一下了
    // std::string zookeeper_ip = service_config.Load("zookeeperip");
    // std::string zookeeper_port = service_config.Load("zookeeperport"); 

    ZkClient zkcli;
    zkcli.Start(); //连接zk服务器
    std::string method_path = "/"+service_name+"/"+method_name;
    //127.0.0.1:8000
    std::string host_data = zkcli.GetData(method_path.c_str());
    if(host_data==""){
        controller->SetFailed(method_path+" is not exist!");
        return;
    }
    int idx = host_data.find(":");
    if(idx==-1){
        controller->SetFailed(method_path+" address is invalid!");
        return;
    }
    std::string rpcservice_ip = host_data.substr(0,idx);
    uint16_t rpcservice_port = std::stoi(host_data.substr(idx+1,host_data.size()));




    
    sockaddr_in rpcserver_addr;
    rpcserver_addr.sin_family = AF_INET;
    inet_pton(AF_INET,rpcservice_ip.c_str(),&rpcserver_addr.sin_addr.s_addr);
    rpcserver_addr.sin_port = htons((rpcservice_port));
    if(connect(clientfd,(sockaddr*)&rpcserver_addr,sizeof(rpcserver_addr))==-1){
        // std::cout<<"connect error! errno: "<<errno<<std::endl;
         char errtxt[512] = {0};
        sprintf(errtxt,"connect error! errno: %d",errno);
        controller->SetFailed(errtxt);
        close(clientfd);
        exit(EXIT_FAILURE);
    }

    //发送rpc请求
    if(send(clientfd,send_rpc_str.c_str(),send_rpc_str.size(),0)==-1){
        // std::cout<<"send error! errno: "<<errno<<std::endl;
        char errtxt[512] = {0};
        sprintf(errtxt,"send error! errno: %d",errno);
        controller->SetFailed(errtxt);
        close(clientfd);
        return;
    }

    //接收rpc请求的响应值
    char recv_buf[1024]={0};
    int recv_size = 0;
    if((recv_size=recv(clientfd,recv_buf,1024,0))==-1){
        // std::cout<<"recv error! errno: "<<errno<<std::endl;
        char errtxt[512] = {0};
        sprintf(errtxt,"recv error! errno: %d",errno);
        controller->SetFailed(errtxt);
        
        close(clientfd);
        return;
    }

    // std::string response_str(recv_buf,0,recv_size);
    // if(response->ParseFromString(response_str))//bug出现问题，recv_buf中遇到\0后面的数据就存不下来了
   if(response->ParseFromArray(recv_buf,recv_size)) 
    {   
        std::cout<<"parse success!"<<std::endl;
        close(clientfd);
        return;
    }
    else{
        // std::cout<<"response parse error!"<<std::endl;
        char errtxt[512] = {0};
        sprintf(errtxt,"response parse error! response_str:%s",recv_buf);
        controller->SetFailed(errtxt);
        close(clientfd);
        return;
    }

}